


public class Board {
	
	public static final int ROWS = 22;
	public static final int COLUMNS = 10;
	public static final int VISIBLE_ROWS = 20;
	public static final int VISIBLE_COLUMNS = 10;
	public static final int VISIBLE_LEFT = 0;
	public static final int VISIBLE_TOP = 2;
	
	public enum TetroState {
		WAITING, // waiting to be inserted (ARE)
		FALLING, // regular fall
		LANDING, // touching the floor
		LOCKING, // being locked in place
		CLEARING // clearing one or more lines
	}
	//state durations in milliseconds
	//FIXME values
	public static final int ARE_LENGTH = 150;// entry delay between a lock and a new tetro
	public static final int FALLING_LENGTH = 1000; // initial fall delay
	public static final int LANDING_LENGTH = 500; // fixed delay before locking the tetro
	public static final int LOCKING_LENGTH = 150;// when a tetro hit the floor before it's locked in place
	public static final int LINE_CLEAR_LENGTH = 400; //delay between line clear and ARE state
	public static final int DAS_LENGTH = 25; // Delayed Auto Shift
	
	protected boolean paused;
	protected boolean gameOver;
	protected byte board[][]; // matrix of Tetro.ID_X, (x=0,y=0) is the top left corner 
	protected Tetro tetro; // active tetro
	protected TetroState tetroState;
	protected int tetroX; // can be negative as a tetro may not fill the entire matrix
	protected int tetroY; // same
	protected Tetro heldTetro;
	protected int[] nextTetros; // array of tetro IDs
	protected int level;
	protected int score;
	protected int nbLinesDone;
	
	
	protected boolean checkCollision(int x, int y, Tetro t){
		// x and y can be negative
		// returns true if the tetro at (x,y) collide with blocks on the board
		//  or if it is outside the board
		
		if ( (x + t.getLeft() < 0) || (x + t.getRight() > COLUMNS) ||
				(y + t.getTop() < 0) || (y + t.getBottom() > ROWS)
			) {
			// occupied cells outside the board
			return true;
		}
		
		byte[][] mat = t.getMatrix();
		
		for (int i = t.getLeft() ; i < t.getRight() ; i++) {
			for (int j = t.getTop() ; j < t.getBottom() ; j++) {
				if ((mat[i][j] > 0) && (board[x+i][y+j] > 0)) {
					return true;
				}
			}
		}
		return false;
	}
		
	public int getGhostY() {
		int y = tetroY;
		while ( !checkCollision(tetroX, y, tetro) ) {
			y++;
		}
		return y;
	}
	
	public void printBoard() {
		for (int i = 0 ; i < ROWS ; i++) {
			for (int j = 0 ; j < COLUMNS ; j++) {
				System.out.print(board[i][j]);
			}
			System.out.println();
		}
	}

	public boolean isPaused() {
		return paused;
	}

	public boolean isGameOver() {
		return gameOver;
	}

	public byte[][] getBoard() {
		return board;
	}

	public Tetro getTetro() {
		return tetro;
	}

	public TetroState getTetroState() {
		return tetroState;
	}

	public int getTetroX() {
		return tetroX;
	}

	public int getTetroY() {
		return tetroY;
	}

	public Tetro getHeldTetro() {
		return heldTetro;
	}

	public int[] getNextTetros() {
		return nextTetros;
	}

	public int getLevel() {
		return level;
	}

	public int getScore() {
		return score;
	}

	public int getNbLinesDone() {
		return nbLinesDone;
	}
}